package com.raidan.dclog.core;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.raidan.dclog.face.IVisual;

/**
 * Config class. Using apache config
 * 
 * @author raidan
 * 
 */
public class Config {

	private final static Logger logger = LoggerFactory.getLogger(Config.class);

	private Config() {
		//
	}

	private static volatile Config instance;

	/**
	 * Singleton ^_^
	 * 
	 * @return instance of config class
	 */
	public static synchronized Config getInstance() {
		if (instance == null) {
			instance = new Config();
			instance.prepareConfig();
		}
		return instance;
	}

	private final static String DEFAULT_CONFIG_NAME = "config.properties";
	private Configuration configInstance;

	protected void prepareConfig() {
		this.prepareConfig(configName == null ? DEFAULT_CONFIG_NAME : configName);
	}

	protected void prepareConfig(String configName) {
		try {
			logger.trace("Loading config from file {}.", configName);

			configInstance = new PropertiesConfiguration(configName);
		} catch (ConfigurationException e) {
			throw new RuntimeException(e);
		}
	}

	private String configName = null;

	public void setConfigName(String configName) {
		this.configName = configName;
		this.prepareConfig();
	}

	public void resetConfigName() {
		this.configName = null;
		this.prepareConfig();
	}

	private String sqlConfigName = null;

	public void setSqlConfigName(String sqlConfigName) {
		if (Database.getInstance().hasConnection()) {
			throw new IllegalStateException("You can't change driver after receiving connection.");
		}
		this.sqlConfigName = sqlConfigName;
	}

	public void resetSqlConfigName() {
		if (this.sqlConfigName != null) {
			if (Database.getInstance().hasConnection()) {
				throw new IllegalStateException("You can't change driver after receiving connection.");
			}
			this.sqlConfigName = null;
		}
	}

	private final static String DEFAULT_SQL_CONFIG_NAME = "sql-connection.properties";

	// SQLite3 has problems with correct handling of data-types
	// private final static String DEFAULT_SQL_CONFIG_NAME =
	// "sqlite3-experimental-connection.properties";

	public String getSqlConfigName() {
		return this.sqlConfigName == null ? DEFAULT_SQL_CONFIG_NAME : this.sqlConfigName;
	}

	public String getBaseLogDirectory() {
		return this.configInstance.getString("baseLogDirectory", "Logs/");
	}

	public boolean isCommitEveryBatch() {
		return this.configInstance.getBoolean("commitEveryBatch", false);
	}

	public int getBatchBulkSize() {
		return this.configInstance.getInt("batchBulkSize", 1000);
	}

	public String getDefaultEncoding() {
		return this.configInstance.getString("defaultEncoding", "UTF-8");
	}

	public String getReportDir() {
		return this.configInstance.getString("reportDir", "reports/");
	}

	public int getMaxIncorrectLines() {
		return this.configInstance.getInt("maxIncorrectLines", 100);
	}

	public String getQueryMacrosValue(String templateName, String macrosName) {
		return this.configInstance.getString("query." + templateName + "." + macrosName);
	}

	private IVisual progressInterface;

	/**
	 * Registering visual interface (for progress bar)
	 * 
	 * @param progressInterface
	 */
	public void setIProgressInstance(IVisual progressInterface) {
		this.progressInterface = progressInterface;
	}

	/**
	 * Return registered visual interface
	 * 
	 * @return
	 */
	public IVisual getProgressInstance() {
		if (this.progressInterface == null) {
			throw new IllegalStateException("Internal error. Progress interface does not setup yet.");
		}
		return this.progressInterface;
	}

}